package com.example.demo01;


import java.io.Serializable;

/**
 * description: MyArrayList <br>
 * date: 2021/2/2 14:02 <br>
 *
 * @author: ZhangYixin <br>
 * version: 1.0 <br>
 */
public class MyArrayList implements Serializable {

    // 使用这个字段来判断当前集合类是否被并发修改，即迭代器并发修改的fail-fast机制
    private transient int modCount = 0;

    // 第一次扩容
    private static final int DEFAULT_CAPACITY =10;

    // 用于初始化空的list
    private static final Object[] EMPTY_ELEMENT_DATA = {};

    // 实际存储元素 transient不被序列化
    transient Object[] elementData;

    //实际list集合大小，从0开始
    private int size;

    public MyArrayList() {
        this.elementData=EMPTY_ELEMENT_DATA;
    }

    public MyArrayList(int initialCapacity){
        if (initialCapacity > 0){
            this.elementData = new Object[initialCapacity];
        }else if (initialCapacity == 0){
            this.elementData = EMPTY_ELEMENT_DATA;
        }else {
            throw new IllegalArgumentException("参数异常");
        }
    }

    public boolean add (Object e){
        //用于并发判断
        modCount++;

        // 判断容量
        ensureCapacityInternal(size+1);

        // 使用下标赋值，尾部插入
        elementData[size++] = e;

        return true;
    }

    /**
     *  计算容量+确保容量
     * @param minCapacity
     */
    private void ensureCapacityInternal(int minCapacity) {

        // 如果是初次扩容 则使用默认的容量
        if (elementData == EMPTY_ELEMENT_DATA){
            minCapacity = Math.max(DEFAULT_CAPACITY,minCapacity);
        }

        // 是否需要扩容，需要的最少容量大于现在数组的长度则要扩容
        if (minCapacity - elementData.length > 0){
            int oldCapacity = elementData.length;

            int newCapacity = oldCapacity + (oldCapacity >> 1);

            // 如果新容量小于最小容量则将最小的容量赋值给新容量
            if (newCapacity - minCapacity < 0){
                newCapacity = minCapacity;
            }

            // 创建新数组
            Object[] objects = new Object[newCapacity];

            // 将旧数组拷贝到新数组中
            System.arraycopy(elementData,0,objects,0,elementData.length);

            // 修改引用
            elementData = objects;

        }

    }

    /**
     * 通过下标获取对象
     * @param index
     * @return
     */
    public Object get (int index){
        rangeCheck(index);
        return elementData[index];
    }

    /**
     * 判断下标是否越界
     * @param index
     */
    private void rangeCheck(int index){
        if (index > size || index < 0){
            throw new IndexOutOfBoundsException("数组越界异常");
        }
    }

    /**
     * 返回对象所在位置
     * @param o
     * @return
     */
    public int indexOf(Object o){
        if (o == null){
            for (int i = 0; i < size ; i++) {
                if (elementData[i] == null){
                    return i;
                }
            }
        }else {
            for (int i = 0; i < size; i++) {
                if (elementData[i].equals(o)){
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * 根据下标设置值
     * @param index
     * @param o
     * @return
     */
    public Object set (int index , Object o){
        //用于并发判断
        modCount++;
        rangeCheck(index);

        Object oldValue = elementData[index];
        elementData[index] = o;

        return oldValue;
    }

    /**
     * 根据下标删除元素
     * @param index
     * @return
     */
    public Object remove (int index ){
        //用于并发判断
        modCount++;
        rangeCheck(index);

        Object oldValue = elementData[index];

        // 计算要删除的位置后面有几个元素
        int moveNum = size-index-1;

        if (moveNum > 0){
            System.arraycopy(elementData,index+1,elementData,index,moveNum);
        }
        // 删除一个，所以要将多出的位置设置为空
        // 如果不置空，将会保存一个引用，可能会出现内存泄漏
        elementData[--size] = null;

        return oldValue;
    }

    // 返回数组大小
    public int size (){
        return this.size;
    }
}
